
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD_LEN 10
#include "nfa.h"

char** getStrArr(int size, int stringLen) {
    
    int i;
    char** arr = (char**)malloc( sizeof(char*) * size );
    
    for (i = 0; i < size; i++) {
        arr[i] = (char*)malloc( sizeof(char) * stringLen );
    }
    
    return arr;

}

NFA* createNFA(void) {
    
    NFA* inputNFA;
    int i;
    
    inputNFA = (NFA*)malloc( sizeof(NFA) );
    
    /* states */
    inputNFA->statesNum = 3;
    inputNFA->states = getStrArr(inputNFA->statesNum, MAX_WORD_LEN);
    inputNFA->states[0] = "q1";
    inputNFA->states[1] = "q2";
    inputNFA->states[2] = "q3";
    
    /* initial and final states */
    inputNFA->initStateIndex = 0;
    inputNFA->finalStatesNum = 1;
    inputNFA->finalStatesIndices = (int*)calloc(sizeof(int), inputNFA->finalStatesNum);
    inputNFA->finalStatesIndices[0] = 0;
    
    /* alphabet */
    inputNFA->alphabetSize = 3;
    inputNFA->alphabet = getStrArr(inputNFA->alphabetSize, MAX_WORD_LEN);
    inputNFA->alphabet[0] = "e";
    inputNFA->alphabet[1] = "a";
    inputNFA->alphabet[2] = "b";
    inputNFA->epsilonIndex = 0;
    
    /* transitions */
    inputNFA->transTblSize = 6; /*inputNFA->statesNum * inputNFA->alphabetSize*/
    inputNFA->transTbl = (Transition*)malloc( sizeof(Transition) * inputNFA->transTblSize );
    
    inputNFA->transTbl[0].source = 0;
    inputNFA->transTbl[0].symbol = 0;
    inputNFA->transTbl[0].destination = 2;

    inputNFA->transTbl[1].source = 0;
    inputNFA->transTbl[1].symbol = 2;
    inputNFA->transTbl[1].destination = 1;

    inputNFA->transTbl[2].source = 1;
    inputNFA->transTbl[2].symbol = 1;
    inputNFA->transTbl[2].destination = 1;

    inputNFA->transTbl[3].source = 1;
    inputNFA->transTbl[3].symbol = 1;
    inputNFA->transTbl[3].destination = 2;

    inputNFA->transTbl[4].source = 1;
    inputNFA->transTbl[4].symbol = 2;
    inputNFA->transTbl[4].destination = 2;

    inputNFA->transTbl[5].source = 2;
    inputNFA->transTbl[5].symbol = 1;
    inputNFA->transTbl[5].destination = 0;
    
    return inputNFA;
}

NextClosureStates* createNextClosureForStates(NFA* nfa) {
    
    /* identifying states with their indices */
    int i;
    
    /* create state closure arrays */
    NextClosureStates* nextClosures = (NextClosureStates*)calloc(sizeof(NextClosureStates),nfa->statesNum);
    for (i = 0; i < nfa->statesNum; i++) {
        nextClosures[i].state = i;
        nextClosures[i].nextStates = (int*)calloc(sizeof(int),nfa->statesNum);
        nextClosures[i].nextStateSymbols = (int*)calloc(sizeof(int),nfa->statesNum);
        nextClosures[i].nextStatesSize = 0;
        nextClosures[i].closureStates = (int*)calloc(sizeof(int),nfa->statesNum);
        nextClosures[i].closureSize = 0;
    }
    
    /* check through all transitions */
    for (i = 0; i < nfa->transTblSize; i++) {
        /* check if transition is on epsilon */
        if (nfa->transTbl[i].symbol == nfa->epsilonIndex) {
            nextClosures[nfa->transTbl[i].source].closureSize++;
            nextClosures[nfa->transTbl[i].source].closureStates[nextClosures[nfa->transTbl[i].source].closureSize] = nfa->transTbl[i].destination;
        } else {
            nextClosures[nfa->transTbl[i].source].nextStatesSize++;
            nextClosures[nfa->transTbl[i].source].nextStates[nextClosures[nfa->transTbl[i].source].nextStatesSize] = nfa->transTbl[i].destination;
            nextClosures[nfa->transTbl[i].source].nextStateSymbols[nextClosures[nfa->transTbl[i].source].nextStatesSize] = nfa->transTbl[i].symbol;
        }
    }
    
    return nextClosures;

}
